#include <STC89C5xRC.H>
#include <INTRINS.H>

sbit LCD_EN=P2^7;
sbit LCD_RS=P2^6;
sbit LCD_WR=P2^5;

#define LCD_DataPort P0

void Delay1ms(void)		//@11.0592MHz
{
	unsigned char i, j;
		_nop_();
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
}

void LCD1602_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_WR=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	Delay1ms();
	LCD_EN=0;
	Delay1ms();
}
void LCD1602_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_WR=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	Delay1ms();
	LCD_EN=0;
	Delay1ms();
}

/**
 * @brief LCD1602初始化
 * @param 无
 * @retval 无
 **/
void LCD1602_Init(void)
{
	LCD1602_WriteCommand(0x38);//八位数据接口，两行显示，5×7点阵
	LCD1602_WriteCommand(0x01);//清楚DDRAM和AC值，光标复位，即清屏
	LCD1602_WriteCommand(0x06);//数据读、写操作后，AC自动加1；画面不动
	LCD1602_WriteCommand(0x0C);//显示开，光标关，闪烁关
}

/**
 * @brief 根据传来的行和列参数，设置光标位置
 * @param 行 列
 * @retval 无
 **/
void LCD1602_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD1602_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD1602_WriteCommand(0x80|((Column-1)+0x40));
	}
}

/**
 * @brief LCD显示单个字符
 * @param 行 列 要显示的字符
 * @retval 
 **/
void LCD1602_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{	
	//设置光标地址
	LCD1602_SetCursor(Line,Column);
	//显示字符
	LCD1602_WriteData(Char);
}

/**
 * @brief LCD显示字符串
 * @param 行 列 要显示的字符串地址
 * @retval 无
 **/
void LCD1602_ShowString(unsigned char Line,unsigned char Column,unsigned char* String)
{
	//设置光标地址
	LCD1602_SetCursor(Line,Column);	
	
	//显示字符串
	while(*String != '\0')
	{
		LCD1602_WriteData(*String);
		String++;
	}
}

/**
 * @brief LCD1602无符号显示数字
 * @param Line:行 Column:列 Num:要显示的数字 NumLong:数字的长度
 * @retval 
 **/
void LCD1602_ShowNum(unsigned char Line,unsigned char Column,unsigned int Num,unsigned char NumLong)
{	
	unsigned char Count=0;
	
	//设置模式：数据读、写操作后，AC自动减1；画面不动
	LCD1602_WriteCommand(0x04);
	
	//设置光标地址
	LCD1602_SetCursor(Line,Column+NumLong-1);	
	
	//发送数字
	while(Num!=0 && Count<NumLong)//判断数字以及其长度的合法性
	{
		LCD1602_WriteData(0x30|(Num%10));
		Num /= 10;
		Count++;
	}
	
	//指定长度大于数字长度，在前面补零
	while(NumLong-Count)
	{
		LCD1602_WriteData(0x30);
		NumLong--;
	}
	
	//恢复AC自动加1的模式
	LCD1602_WriteCommand(0x06);
}

/**
 * @brief 计算x的y次方
 * @param x：底数，y：指数
 * @retval x的y次方 
 **/
unsigned int LCD1602_Pow(char x,char y)
{	
	unsigned char i;
	unsigned int ret=1;
	for(i=0;i<y;i++)
	{
		ret *= x;
	}
	return ret;
}

/**
 * @brief LCD显示有符号数字
 * @param 
 * @retval 
 **/
void LCD1602_ShowSignedNum(unsigned char Line,unsigned char Column,int Num,unsigned char NumLong)
{	
	unsigned char i;
	unsigned int Num1;
	//设置光标地址
	LCD1602_SetCursor(Line,Column);
	
	//显示符号
	if(Num>=0)
	{
		LCD1602_WriteData('+');
		Num1=Num;
	}
	else if(Num<0)
	{
		LCD1602_WriteData('-');
		Num1=-Num;
	}
	
	for(i=NumLong;i>0;i--)
	{
		LCD1602_WriteData('0' + (Num1/LCD1602_Pow(10,i-1))%10);
	}
}

/**
 * @brief LCD显示16进制数字
 * @param 
 * @retval 
 **/
void LCD1602_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Num,unsigned char NumLong)
{
	unsigned char i;
	unsigned char SingleNum;
	//设置光标地址
	LCD1602_SetCursor(Line,Column);
	for(i=NumLong;i>0;i--)
	{
		SingleNum=(Num/LCD1602_Pow(16,i-1))%16;
		if(SingleNum<10)
		{
			LCD1602_WriteData('0' + SingleNum);
		}
		else if(SingleNum>=10)
		{
			LCD1602_WriteData('7' + SingleNum);
		}
	}
}

/**
 * @brief LCD显示2进制数字
 * @param 
 * @retval 
 **/
void LCD1602_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Num,unsigned char NumLong)
{
	unsigned char i;
	unsigned char SingleNum;
	//设置光标地址
	LCD1602_SetCursor(Line,Column);
	for(i=NumLong;i>0;i--)
	{
		SingleNum=(Num/LCD1602_Pow(2,i-1))%2;
		LCD1602_WriteData('0' + SingleNum);
	}
}
